// -------------------------------------------------------------------------
//    @FileName         :    NFCPlayerRedisModule.cpp
//    @Author           :    LvSheng.Huang
//    @Date             :    2013-10-03
//    @Module           :    NFCPlayerRedisModule
//    @Desc             :
// -------------------------------------------------------------------------
#include "NFCPlayerDBModule.h"

NFCPlayerDBModule::NFCPlayerDBModule(NFIPluginManager* p)
{
    pPluginManager = p;
}

bool NFCPlayerDBModule::Init()
{
    m_pClassModule = pPluginManager->FindModule<NFIClassModule>();
    m_pNoSqlModule = pPluginManager->FindModule<NFINoSqlModule>();
    m_pCommonRedisModule = pPluginManager->FindModule<NFICommonDBModule>();
    m_pKernelModule = pPluginManager->FindModule<NFIKernelModule>();
    m_pLogModule = pPluginManager->FindModule<NFILogModule>();

    return true;
}

bool NFCPlayerDBModule::Shut()
{
    return true;
}

bool NFCPlayerDBModule::Execute()
{
    return true;
}

bool NFCPlayerDBModule::AfterInit()
{
    m_pAsyMysqlModule = pPluginManager->FindModule<NFIAsyMysqlModule>();
    m_pAsyNoSqlModule = pPluginManager->FindModule<NFIAsyNoSqlModule>();
    m_pActorModule = pPluginManager->FindModule<NFIActorModule>();
    m_pKernelModule->AddClassCallBack(NFrame::Player::ThisName(), this, &NFCPlayerDBModule::OnObjectPlayerEvent);
    //m_pKernelModule->AddClassCallBack(NFrame::Guild::ThisName(), this, &NFCPlayerRedisModule::OnObjectGuildEvent);
    return true;
}
/*
int64_t NFCPlayerRedisModule::GetPlayerCacheGameID(const NFGUID & self)
{
    NF_SHARE_PTR<NFINoSqlDriver> pNoSqlDriver = m_pNoSqlModule->GetDriverBySuitConsistent();
    if (!pNoSqlDriver)
    {
        return 0;
    }

    std::string strValue;
    int64_t nGameID = 0;
    std::string strKey = GetOnlineGameServerKey();

    if (pNoSqlDriver->HGet(strKey, self.ToString(), strValue))
    {
        try
        {
            nGameID = lexical_cast<int64_t>(strValue);
        }
        catch (...)
        {
        }
    }

    return nGameID;
}

int64_t NFCPlayerRedisModule::GetPlayerCacheProxyID(const NFGUID & self)
{
    NF_SHARE_PTR<NFINoSqlDriver> pNoSqlDriver = m_pNoSqlModule->GetDriverBySuitConsistent();
    if (!pNoSqlDriver)
    {
        return 0;
    }

    std::string strValue;
    int64_t nProxyID = 0;
    std::string strKey = GetOnlineProxyServerKey();

    if (pNoSqlDriver->HGet(strKey, self.ToString(), strValue))
    {
        try
        {
            nProxyID = lexical_cast<int64_t>(strValue);
        }
        catch (...)
        {
        }
    }

    return nProxyID;
}

bool NFCPlayerRedisModule::GetPlayerCacheGameID(const std::vector<std::string>& xList, std::vector<int64_t>& xResultList)
{
    NF_SHARE_PTR<NFINoSqlDriver> pNoSqlDriver = m_pNoSqlModule->GetDriverBySuitConsistent();
    if (!pNoSqlDriver)
    {
        return 0;
    }

    std::string strKey = GetOnlineGameServerKey();
    std::vector<std::string> strValueList;

    if (pNoSqlDriver->HMGet(strKey, xList, strValueList))
    {
        for (int i = 0; i < strValueList.size(); ++i)
        {
            int64_t nGameID = 0;

            try
            {
                nGameID = lexical_cast<int64_t>(strValueList[i]);
            }
            catch (...)
            {
            }

            xResultList.push_back(nGameID);
        }

        return true;
    }

    return false;
}

bool NFCPlayerRedisModule::GetPlayerCacheProxyID(const std::vector<std::string>& xList, std::vector<int64_t>& xResultList)
{
    NF_SHARE_PTR<NFINoSqlDriver> pNoSqlDriver = m_pNoSqlModule->GetDriverBySuitConsistent();
    if (!pNoSqlDriver)
    {
        return 0;
    }

    std::string strKey = GetOnlineProxyServerKey();
    std::vector<std::string> strValueList;

    if (pNoSqlDriver->HMGet(strKey, xList, strValueList))
    {
        for (int i = 0; i < strValueList.size(); ++i)
        {
            int64_t nProxyID = 0;

            try
            {
                nProxyID = lexical_cast<int64_t>(strValueList[i]);
            }
            catch (...)
            {
            }

            xResultList.push_back(nProxyID);
        }

        return true;
    }

    return false;
}
*/

int NFCPlayerDBModule::SendAsynLoadPlayerDataFromMySql(const NFGUID& self, const MYSQL_RETURN_VECKEY_VECVALUE_FUNCTOR& mFunReturnVeckKeyValueRsp, const std::string& strUseData)
{
    std::vector<std::string> fieldVec;
    NF_SHARE_PTR<NFIPropertyManager> pStaticClassPropertyManager = m_pClassModule->GetClassPropertyManager(NFrame::Player::ThisName());
    m_pCommonRedisModule->ConvertPropertyManagerToPB(pStaticClassPropertyManager, fieldVec);
    m_pAsyMysqlModule->Query(self, NFrame::Player::ThisName(), self.ToString(), fieldVec, mFunReturnVeckKeyValueRsp, strUseData);
    return 0;
}

int NFCPlayerDBModule::SendAsynLoadPlayerDataFromRedis(const NFGUID& self, const NOSQL_RETURN_FUNCTOR& mFunReturnRsp)
{
    NFMsg::PackNoSqlParam xMsg;
    xMsg.set_self(self.ToString());
    xMsg.set_cache_property_key(m_pCommonRedisModule->GetPropertyCacheKey(self));
    xMsg.set_cache_record_key(m_pCommonRedisModule->GetRecordCacheKey(self));
    xMsg.set_storage_property_key(m_pCommonRedisModule->GetPropertyStorageKey(self));
    xMsg.set_storage_record_key(m_pCommonRedisModule->GetRecordStorageKey(self));

    m_pAsyNoSqlModule->LoadNFObject(self, xMsg, mFunReturnRsp);
    return 0;
}

void NFCPlayerDBModule::RecvAsynLoadPlayerDataToRedis(const NFGUID& self, NFMsg::PackNoSqlParam& nosqlParam, const std::string& strUseData)
{
    int nRet = nosqlParam.ret();
    if (nRet == 0)
    {
        m_pLogModule->LogNormal(NFILogModule::NLL_INFO_NORMAL, self, "Save Player Data To Redis ", "Success", __FUNCTION__, __LINE__);
    }
    else
    {
        m_pLogModule->LogNormal(NFILogModule::NLL_INFO_NORMAL, self, "Save Player Data To Redis ", "Failed", __FUNCTION__, __LINE__);
    }

    return;
}

void NFCPlayerDBModule::RecvAsynSavePlayerDataToMysql(const NFGUID& self, const int ret, const std::string& strUseData)
{
    m_pLogModule->LogNormal(NFILogModule::NLL_INFO_NORMAL, self, "Save Player Data To Mysql", "", __FUNCTION__, __LINE__);
}

int NFCPlayerDBModule::SendAsynSavePlayerDataToMysql(const NFGUID& self)
{
    NF_SHARE_PTR<NFIObject> pObject = m_pKernelModule->GetObject(self);
    if (pObject == nullptr)
    {
        return false;
    }

    std::vector<std::string> vecField;
    std::vector<std::string> vecValue;
    m_pCommonRedisModule->SaveStroragePropertyInfo(self, pObject->GetPropertyManager(), vecField, vecValue);
    std::string strUseData;
    m_pAsyMysqlModule->Updata(self, NFrame::Player::ThisName(), self.ToString(), vecField, vecValue, this, &NFCPlayerDBModule::RecvAsynSavePlayerDataToMysql, strUseData);
    return 0;
}

int NFCPlayerDBModule::SendAsynSavePlayerDataToRedis(const NFGUID& self)
{
    NF_SHARE_PTR<NFIObject> pObject = m_pKernelModule->GetObject(self);
    if (pObject == nullptr)
    {
        return false;
    }

    NFMsg::PackNoSqlParam xMsg;
    xMsg.set_self(self.ToString());
    xMsg.set_cache_property_key(m_pCommonRedisModule->GetPropertyCacheKey(self));
    xMsg.set_cache_record_key(m_pCommonRedisModule->GetRecordCacheKey(self));
    xMsg.set_storage_property_key(m_pCommonRedisModule->GetPropertyStorageKey(self));
    xMsg.set_storage_record_key(m_pCommonRedisModule->GetRecordStorageKey(self));

    m_pCommonRedisModule->SaveCachePropertyInfo(self, pObject->GetPropertyManager(), *xMsg.mutable_cache_property_value());
    m_pCommonRedisModule->SaveCacheRecordInfo(self, pObject->GetRecordManager(), *xMsg.mutable_cache_record_value());
    m_pCommonRedisModule->SaveStroragePropertyInfo(self, pObject->GetPropertyManager(), *xMsg.mutable_storage_property_value());
    m_pCommonRedisModule->SaveStrorageRecordInfo(self, pObject->GetRecordManager(), *xMsg.mutable_storage_record_value());

    m_pAsyNoSqlModule->SaveNFObject(self, xMsg, this, &NFCPlayerDBModule::RecvAsynLoadPlayerDataToRedis);
    return 0;
}

void NFCPlayerDBModule::RecvAsynLoadPlayerDataFromMysql(const NFGUID& self, const int nRet, const std::vector<std::string>& fieldVec, const std::vector<std::string>& valueVec, const std::string& strUseData)
{
    mxObjectDataCache.RemoveElement(self);

    NF_SHARE_PTR<PlayerDataCache> xPlayerDataCache(NF_NEW PlayerDataCache());
    mxObjectDataCache.AddElement(self, xPlayerDataCache);

    NF_SHARE_PTR<NFIPropertyManager> pStaticClassPropertyManager = m_pClassModule->GetClassPropertyManager(NFrame::Player::ThisName());
    m_pCommonRedisModule->ConvertPropertyManagerToPB(self, pStaticClassPropertyManager, fieldVec, valueVec, xPlayerDataCache->xPbPropertyStorageList);
}

int NFCPlayerDBModule::RecvAsynLoadPlayerDataFromRedis(const NFGUID& self, NFMsg::PackNoSqlParam& xMsg, const std::string& strUseData)
{
    if (xMsg.ret() != 0)
    {
        m_pLogModule->LogNormal(NFILogModule::NLL_INFO_NORMAL, self, "Load Player Data Failed From Redis,", "", __FUNCTION__, __LINE__);
        return -1;
    }

    mxObjectDataCache.RemoveElement(self);

    NF_SHARE_PTR<PlayerDataCache> xPlayerDataCache(NF_NEW PlayerDataCache());
    mxObjectDataCache.AddElement(self, xPlayerDataCache);

    xPlayerDataCache->xPbPropertyCacheList.ParseFromString(xMsg.cache_property_value());
    xPlayerDataCache->xPbPropertyStorageList.ParseFromString(xMsg.storage_property_value());
    xPlayerDataCache->xPbRecordCacheList.ParseFromString(xMsg.cache_record_value());
    xPlayerDataCache->xPbRecordStorageList.ParseFromString(xMsg.storage_record_value());

    return 0;
}

bool NFCPlayerDBModule::LoadPlayerDataFromRedis(const NFGUID& self)
{
    mxObjectDataCache.RemoveElement(self);

    NF_SHARE_PTR<PlayerDataCache> xPlayerDataCache(NF_NEW PlayerDataCache());
    mxObjectDataCache.AddElement(self, xPlayerDataCache);

    m_pCommonRedisModule->LoadCachePropertyListPB(self, xPlayerDataCache->xPbPropertyCacheList);
    m_pCommonRedisModule->LoadStoragePropertyListPB(self, xPlayerDataCache->xPbPropertyStorageList);
    m_pCommonRedisModule->LoadCacheRecordListPB(self, xPlayerDataCache->xPbRecordCacheList);
    m_pCommonRedisModule->LoadStorageRecordListPB(self, xPlayerDataCache->xPbRecordStorageList);

#ifdef NF_DEBUG_MODE
    for (int i = 0; i < xPlayerDataCache->xPbPropertyCacheList.property_int_list_size(); ++i)
    {
        const NFMsg::PropertyInt& xPropertyData = xPlayerDataCache->xPbPropertyCacheList.property_int_list(i);
        const std::string& strPropertyName = xPropertyData.property_name();
        const NFINT64 xPropertyValue = xPropertyData.data();

        m_pLogModule->LogNormal(NFILogModule::NF_LOG_LEVEL::NLL_DEBUG_NORMAL, self, strPropertyName, xPropertyValue, "PbPropertyCacheList", i);
    }

    for (int iRecord = 0; iRecord < xPlayerDataCache->xPbRecordCacheList.record_list_size(); ++iRecord)
    {
        const NFMsg::ObjectRecordBase& xRecordBase = xPlayerDataCache->xPbRecordCacheList.record_list(iRecord);
        const std::string& strRecordName = xRecordBase.record_name();


        for (int iRow = 0; iRow < xRecordBase.row_struct_size(); ++iRow)
        {

            const NFMsg::RecordAddRowStruct& xAddRowStruct = xRecordBase.row_struct(iRow);

            for (int iStr = 0; iStr < xAddRowStruct.record_string_list_size(); iStr++)
            {
                const NFMsg::RecordString& xPropertyData = xAddRowStruct.record_string_list(iStr);
                const int nRow = xPropertyData.row();
                const int nCol = xPropertyData.col();
                const std::string& xPropertyValue = xPropertyData.data();

                std::ostringstream strData;
                strData  << strRecordName << " Row:" << nRow << " Col:" << nCol << " " << xPropertyValue;

                m_pLogModule->LogNormal(NFILogModule::NF_LOG_LEVEL::NLL_DEBUG_NORMAL, self, strData, "xPbRecordCacheList", iRow);
            }
        }
    }
#endif // NF_DEBUG_MODE

    //  for (int i = 0; i < xPlayerDataCache->xPbPropertyCacheList.property_int_list_size(); ++i)
    //  {
    //      const NFMsg::PropertyInt& xPropertyData = xPlayerDataCache->xPbPropertyCacheList.property_int_list(i);
    //      const std::string& strPropertyName = xPropertyData.property_name();
    //      const NFINT64 xPropertyValue = xPropertyData.data();
    //      if (strPropertyName == NFrame::Player::HomeSceneID())
    //      {
    //          xPlayerDataCache->nHomeSceneID = xPropertyValue;
    //          break;
    //      }
    //  }

    return true;
}

bool NFCPlayerDBModule::SavePlayerDataToRedis(const NFGUID& self)
{
    NF_SHARE_PTR<NFIObject> pObject = m_pKernelModule->GetObject(self);
    if (pObject == nullptr)
    {
        return false;
    }

    m_pCommonRedisModule->SaveCachePropertyInfo(self, pObject->GetPropertyManager());
    m_pCommonRedisModule->SaveCacheRecordInfo(self, pObject->GetRecordManager());

    m_pCommonRedisModule->SaveStroragePropertyInfo(self, pObject->GetPropertyManager());
    m_pCommonRedisModule->SaveStrorageRecordInfo(self, pObject->GetRecordManager());

    return true;
}

const bool NFCPlayerDBModule::AttachData(const NFGUID& self)
{
    NF_SHARE_PTR<PlayerDataCache> xPlayerDataCache = mxObjectDataCache.GetElement(self);
    if (xPlayerDataCache)
    {
        //way 1:load first then create object, especially we have loaded nosql plugin
        NF_SHARE_PTR<NFIObject> pObject = m_pKernelModule->GetObject(self);
        if (pObject)
        {
            NF_SHARE_PTR<NFIPropertyManager> pPropertyManager = pObject->GetPropertyManager();
            NF_SHARE_PTR<NFIRecordManager> pRecordManager = pObject->GetRecordManager();

            m_pCommonRedisModule->ConvertPBToPropertyManager(xPlayerDataCache->xPbPropertyCacheList, pPropertyManager, true);
            m_pCommonRedisModule->ConvertPBToPropertyManager(xPlayerDataCache->xPbPropertyStorageList, pPropertyManager, false);
            m_pCommonRedisModule->ConvertPBToRecordManager(xPlayerDataCache->xPbRecordCacheList, pRecordManager, true);
            m_pCommonRedisModule->ConvertPBToRecordManager(xPlayerDataCache->xPbRecordStorageList, pRecordManager, false);

            return true;
        }
    }

    return false;
}

int NFCPlayerDBModule::OnObjectPlayerEvent(const NFGUID& self, const std::string& strClassName, const CLASS_OBJECT_EVENT eClassEvent, const NFDataList& var)
{
    if (CLASS_OBJECT_EVENT::COE_CREATE_LOADDATA == eClassEvent)
    {
        AttachData(self);
    }
    else if (CLASS_OBJECT_EVENT::COE_CREATE_FINISH == eClassEvent)
    {
        mxObjectDataCache.RemoveElement(self);
    }

    return 0;
}
